use crate::models::{NewType, Type};
use crate::schema::types::dsl::*;
use crate::utils;
use diesel::prelude::*;
use diesel::MysqlConnection;

pub fn insert(
    conn: &MysqlConnection,
    mut new_type: NewType,
) -> std::result::Result<usize, diesel::result::Error> {
    new_type.id = utils::uuid_str();
    let result = diesel::insert_into(types).values(&new_type).execute(conn)?;
    Ok(result)
}

pub fn update(
    conn: &MysqlConnection,
    new_type: NewType,
) -> std::result::Result<usize, diesel::result::Error> {
    let result = diesel::update(types.filter(id.eq(new_type.id)))
        // 此处有坑,set中的字段顺序,必须和models.rs中的结构体的字段顺序一模一样,否则报错
        .set((
            pid.eq(new_type.pid),
            name.eq(new_type.name),
            rank.eq(new_type.rank),
            description.eq(new_type.description),
            keyword.eq(new_type.keyword),
            icon.eq(new_type.icon),
            pic.eq(new_type.pic),
            hidden.eq(new_type.hidden),
        ))
        .execute(conn)?;
    Ok(result)
}

pub fn get_all(
    show_hidden: bool,
    conn: &MysqlConnection,
) -> std::result::Result<Vec<Type>, diesel::result::Error> {
    if show_hidden {
        return types.order(rank.desc()).then_order_by(created_at.asc()).load::<Type>(conn);
    }
    types
        .filter(hidden.eq(show_hidden))
        .order(rank.desc())
        .then_order_by(created_at.asc())
        .load::<Type>(conn)
}

//根据 id 获取属于该 id 的所有子分类
pub fn get_all_children(
    id_str: String,
    show_hidden: bool,
    conn: &MysqlConnection,
) -> std::result::Result<Vec<Type>, diesel::result::Error> {
    if show_hidden {
        types
            .filter(pid.eq(id_str))
            .order(rank.desc())
            .then_order_by(created_at.asc())
            .load::<Type>(conn)
    } else {
        types
            .filter(hidden.eq(show_hidden))
            .filter(pid.eq(id_str))
            .order(rank.desc())
            .then_order_by(created_at.asc())
            .load::<Type>(conn)
    }
}

pub fn get(
    id_str: String,
    conn: &MysqlConnection,
) -> std::result::Result<Type, diesel::result::Error> {
    types.filter(id.eq(id_str)).first::<Type>(conn)
}

pub fn delete(
    id_str: String,
    conn: &MysqlConnection,
) -> std::result::Result<usize, diesel::result::Error> {
    diesel::delete(types).filter(id.eq(id_str)).execute(conn)
}
